home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 23
/
AACD 23.iso
/
AACD
/
Online
/
opennap
/
metaserver.c
< prev
next >
Wrap
C/C++ Source or Header
|
2001-06-08
|
7KB
|
275 lines
/* Copyright (C) 2000-1 drscholl@users.sourceforge.net
This is free software distributed under the terms of the
GNU Public License. See the file COPYING for details.
$Id: metaserver.c,v 1.18 2001/02/15 08:39:45 drscholl Exp $ */
/* a simple napster metaserver. redirects clients to a specific set of
servers */
/* Modified 29/05/01 : Added include "confdefs.h" since we are not using the
for Amiga port : CONFIGURE script
Added define for htons(), which is not defined in the
Amiga GCC 2.7.0 includes
Added value for __auto_socket_vers to permit automatic
opening/closing of bsdsocket.library by socket.o
Added include "extrasocket.h" with inlines for a few
bsdsocket.library functions not emulated by ixemul
Removed openlog() and closelog() calls, not needed by
bsdsocket.library
30/05/01 : Added varargs stub syslog() outside extrasocket.h. I
intended to have this in extrasocket.h itself, but in
another file there is a conflicting declaration of
syslog().
*/
#include "confdefs.h"
#define htons(x) (x)
unsigned long __auto_socket_vers = 4;
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <limits.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#if HAVE_POLL
#include <sys/poll.h>
#endif /* HAVE_POLL */
#include <syslog.h>
#include "extrasocket.h"
/* varargs stub for syslog() */
void syslog(int level, const char * format, ...)
{
vsyslog(level, format, (&format) + 1);
}
#ifdef __CYGWIN__
extern char *optarg;
extern int optind;
#endif
char metafile[_POSIX_PATH_MAX];
char *hosts[64];
int numhosts = 0;
volatile int sig_meta = 0;
#ifndef HAVE_SOCKLEN_T
typedef unsigned int socklen_t;
#endif
static void
handler (int sig)
{
if (sig == SIGHUP)
sig_meta++;
}
static void
usage (void)
{
puts
("usage: metaserver [ -fsv ] [ -c CONFIG ] [ -l IP ] [ -p <port> ] [ host:port ... ]");
puts (" -c CONFIG use list of servers in file CONFIG");
puts (" -f run the metaserver in the background");
puts (" -v display version number and exit");
puts (" -l IP listen only on interface for IP");
puts (" -p <port> listen for connection on <port> (default is 8875)");
puts (" -s disable syslog messages");
puts ("\n if no arguments are given, defaults to 127.0.0.1:8888");
exit (1);
}
static void
read_metafile (char *filename)
{
char buffer[90];
FILE *fp;
fp = fopen (filename, "r");
if (!fp)
return;
while (fgets (buffer, sizeof (buffer) - 1, fp))
{
buffer[strlen (buffer) - 1] = 0;
if (strlen (buffer) > 0 && buffer[0] != '#')
hosts[numhosts++] = strdup (buffer);
}
fclose (fp);
}
int
main (int argc, char **argv)
{
struct sockaddr_in sin;
int i, s, f, port = 8875;
int location = 0;
int sys_log = 1;
int background = 0;
#if HAVE_POLL
struct pollfd ufd;
#else
fd_set set;
#endif /* HAVE_POLL */
socklen_t sinsize;
struct sigaction sa;
unsigned int iface = INADDR_ANY;
metafile[0] = 0;
while ((i = getopt (argc, argv, "hfl:vp:c:s")) != EOF)
{
switch (i)
{
case 'l':
iface = inet_addr (optarg);
break;
case 'p':
port = atoi (optarg);
break;
case 'c':
strcpy (metafile, optarg);
break;
case 'f':
background ^= 1;
break;
case 's':
sys_log ^= 1;
break;
case 'v':
printf ("%s metaserver version %s\n", PACKAGE, VERSION);
exit (1);
default:
usage ();
}
}
/* read in the host list */
if (!metafile[0])
{
if (!argv[optind])
hosts[numhosts++] = strdup ("127.0.0.1:8888"); /* use default host */
else
{
while (argv[optind])
{
hosts[numhosts++] = strdup (argv[optind]);
optind++;
}
}
}
else
read_metafile (metafile);
/* set some signal handlers so we can shut down gracefully */
memset (&sa, 0, sizeof (sa));
sa.sa_handler = handler;
sigaction (SIGINT, &sa, 0);
sigaction (SIGTERM, &sa, 0);
#ifndef __CYGWIN__
sa.sa_flags = SA_RESTART;
#endif
sigaction (SIGHUP, &sa, NULL);
memset (&sin, 0, sizeof (sin));
sin.sin_port = htons (port);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = iface;
s = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s < 0)
{
perror ("socket");
exit (1);
}
if (bind (s, (struct sockaddr *) &sin, sizeof (sin)) < 0)
{
perror ("bind");
exit (1);
}
if (listen (s, 50) < 0)
{
perror ("listen");
exit (1);
}
if (background && fork ())
_exit (0);
/* if (sys_log)
openlog ("metaserver", LOG_PID, LOG_LOCAL6); */
location = 0;
#if HAVE_POLL
memset (&ufd, 0, sizeof (ufd));
ufd.fd = s;
ufd.events = POLLIN | POLLHUP;
#endif /* HAVE_POLL */
for (;;)
{
#if HAVE_POLL
i = poll (&ufd, 1, -1);
#else
FD_ZERO (&set);
FD_SET (s, &set);
i = select (s + 1, &set, 0, 0, 0);
#endif /* HAVE_POLL */
if (i == -1)
{
/* re-read configuration files */
if (sig_meta)
{
for (i = 0; i < numhosts; i++)
free (hosts[i]);
numhosts = 0;
location = 0;
sig_meta = 0;
read_metafile (metafile);
continue;
}
perror (
#if HAVE_POLL
"poll"
#else
"select"
#endif
);
break;
}
sinsize = sizeof (sin);
f = accept (s, (struct sockaddr *) &sin, &sinsize);
if (f < 0)
{
perror ("accept");
break;
}
write (f, hosts[location], strlen (hosts[location]));
write (f, "\n", 1);
if (sys_log)
syslog (LOG_ERR, "Redirecting %s to %s", inet_ntoa (sin.sin_addr),
hosts[location]);
location = (location + 1) % numhosts;
close (f);
}
close (s);
/* closelog (); */
exit (0);
}